package com.beemans.corekit.integration.topon;

import android.view.View;
import android.view.ViewGroup;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.LifecycleOwner;

import com.anythink.core.api.ATAdConst;
import com.anythink.core.api.ATAdInfo;
import com.anythink.core.api.ATAdStatusInfo;
import com.anythink.core.api.AdError;
import com.anythink.nativead.api.ATNative;
import com.anythink.nativead.api.ATNativeAdView;
import com.anythink.nativead.api.ATNativeDislikeListener;
import com.anythink.nativead.api.ATNativeEventListener;
import com.anythink.nativead.api.ATNativeNetworkListener;
import com.anythink.nativead.api.ATNativePrepareExInfo;
import com.anythink.nativead.api.NativeAd;

import java.util.HashMap;
import java.util.Map;

public class NativeAdvert extends BaseAdvert implements ATNativeNetworkListener, ATNativeEventListener {
    @NonNull
    private final LifecycleOwner lifecycleOwner;
    @NonNull
    private final NativeAdvertConfig advertConfig;
    @Nullable
    private final FragmentActivity fragmentActivity;
    @Nullable
    private final ATNativeAdView atNativeAdView;

    @Nullable
    private INativeSelfRender nativeSelfRender;
    @Nullable
    private NativeAdvertCallback advertCallback;
    @Nullable
    private ATNative atNative;
    @Nullable
    private NativeAd nativeAd;

    private boolean isAdvertLoadFailed = false;

    public NativeAdvert(
            @NonNull LifecycleOwner lifecycleOwner,
            @NonNull NativeAdvertConfig advertConfig
    ) {
        this(lifecycleOwner, advertConfig, null, null, null);
    }

    public NativeAdvert(
            @NonNull LifecycleOwner lifecycleOwner,
            @NonNull NativeAdvertConfig advertConfig,
            @Nullable ATNativeAdView atNativeAdView,
            @Nullable INativeSelfRender nativeSelfRender,
            @Nullable NativeAdvertCallback advertCallback
    ) {
        this.lifecycleOwner = lifecycleOwner;
        this.advertConfig = advertConfig;
        this.atNativeAdView = atNativeAdView;
        this.nativeSelfRender = nativeSelfRender;
        this.advertCallback = advertCallback;
        this.fragmentActivity = AdvertLifeUtils.getContext(lifecycleOwner);

        if (fragmentActivity == null) {
            return;
        }

        atNative = new ATNative(fragmentActivity, advertConfig.getPlacementId(), this);

        // 配置广告宽高
        final Map<String, Object> localMap = new HashMap<>();
        localMap.put(ATAdConst.KEY.AD_WIDTH, advertConfig.getAdvertWidth());
        localMap.put(ATAdConst.KEY.AD_HEIGHT, advertConfig.getAdvertHeight());

        atNative.setLocalExtra(localMap);

        if (atNativeAdView != null) {
            final ViewGroup.LayoutParams layoutParams = atNativeAdView.getLayoutParams();
            if (layoutParams != null) {
                if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) {
                    layoutParams.width = advertConfig.getAdvertWidth();
                }
                atNativeAdView.setLayoutParams(layoutParams);
            }
        }

        AdvertLifeUtils.launchWhenDestroy(lifecycleOwner, this::onAdvertRelease);

        if (advertCallback != null) {
            advertCallback.onAdvertStart(this);
        }
    }

    /**
     * @return 广告是否准备完毕
     */
    @Override
    public boolean isAdvertReady() {
        if (atNative == null) {
            return false;
        }
        final ATAdStatusInfo atAdStatusInfo = atNative.checkAdStatus();
        return atAdStatusInfo != null && atAdStatusInfo.isReady();
    }

    /**
     * 广告是否正在加载
     */
    @Override
    public boolean isAdvertLoading() {
        if (atNative == null) {
            return false;
        }
        final ATAdStatusInfo atAdStatusInfo = atNative.checkAdStatus();
        return atAdStatusInfo != null && atAdStatusInfo.isLoading();
    }

    @Override
    public void onAdvertRelease() {
        super.onAdvertRelease();

        if (advertCallback != null) {
            advertCallback = null;
        }
        if (atNative != null) {
            try {
                atNative.setAdListener(null);
                atNative.setAdSourceStatusListener(null);
            } catch (Throwable ignored) {
            }
            atNative = null;
        }
        if (nativeAd != null) {
            try {
                nativeAd.destory();
            } catch (Throwable ignored) {
            }
            nativeAd = null;
        }
        if (atNativeAdView != null) {
            atNativeAdView.removeAllViews();
        }
    }

    /**
     * 加载广告
     */
    @Override
    protected void loadAdvert() {
        loadAdvert(false);
    }

    private void loadAdvert(boolean isPreloadAdvert) {
        isAdvertLoadFailed = false;

        if (atNative == null) {
            return;
        }
        if ((!isPreloadAdvert || !advertConfig.isPreloadWithoutReady()) && isAdvertReady()) {
            onAdvertLoaded(false);
            return;
        }

        waitForAdvertToLoad(() -> {
            if (isAdvertReady()) {
                onAdvertLoaded(false);
                return;
            }
            if (atNative != null) {
                onAdvertRequestPre();

                try {
                    atNative.makeAdRequest();
                } catch (Throwable throwable) {
                    onAdvertLoadFail(throwable.getMessage());
                }
            }
        });
    }

    /**
     * 展示广告
     */
    private void showAdvert() {
        onAdvertRender();
    }

    /**
     * 广告渲染
     */
    private void onAdvertRender() {
        if (atNativeAdView == null) {
            onAdvertShowFail();
            return;
        }
        if (!isAdvertReady()) {
            onAdvertShowFail();
            return;
        }

        final NativeAd nativeAd = (atNative != null) ? atNative.getNativeAd() : null;
        if (nativeAd == null) {
            onAdvertShowFail();
            return;
        }

        if (this.nativeAd != null) {
            try {
                this.nativeAd.destory();
            } catch (Throwable ignored) {
            }
        }
        this.nativeAd = nativeAd;
        atNativeAdView.removeAllViews();

        nativeAd.setNativeEventListener(this);
        nativeAd.setDislikeCallbackListener(new ATNativeDislikeListener() {
            @Override
            public void onAdCloseButtonClick(ATNativeAdView atNativeAdView, ATAdInfo atAdInfo) {
                if (advertCallback != null) {
                    advertCallback.onAdvertClose(NativeAdvert.this, atAdInfo);
                }

                onAdvertRelease();
            }
        });
        nativeAd.setAdRevenueListener(atAdInfo -> {
            if (advertCallback != null) {
                advertCallback.onAdvertRevenue(this, atAdInfo);
            }
        });

        final ATNativePrepareExInfo atNativePrepareExInfo = new ATNativePrepareExInfo();

        // 模板
        if (nativeAd.isNativeExpress()) {
            try {
                nativeAd.renderAdContainer(atNativeAdView, null);
                nativeAd.prepare(atNativeAdView, atNativePrepareExInfo);
            } catch (Throwable ignored) {
                onAdvertShowFail();
            }
            return;
        }

        // 自渲染
        if (advertCallback != null) {
            final INativeSelfRender selfRender = advertCallback.createSelfRender(nativeAd.getAdInfo());
            if (selfRender != null) {
                nativeSelfRender = selfRender;
            }
        }
        if (nativeSelfRender != null && fragmentActivity != null) {
            try {
                nativeSelfRender.onBindView(fragmentActivity, nativeAd.getAdMaterial(), atNativePrepareExInfo);

                final View selfRenderView = nativeSelfRender.getSelfRenderView();
                nativeAd.renderAdContainer(atNativeAdView, selfRenderView);
                nativeAd.prepare(atNativeAdView, atNativePrepareExInfo);
            } catch (Throwable ignored) {
                onAdvertShowFail();
            }
        } else {
            onAdvertShowFail();
        }
    }

    private void onAdvertRequestPre() {
        if (advertCallback != null) {
            final ATAdInfoExt adInfoExt = new ATAdInfoExt();
            adInfoExt.adunit_id = advertConfig.getPlacementId();
            adInfoExt.adunit_format = AdUnitFormat.NATIVE.getValue();
            advertCallback.onAdvertRequestPre(this, adInfoExt);
        }
    }

    private void onAdvertRequestAlt() {
        if (advertCallback != null) {
            final ATAdInfoExt adInfoExt = new ATAdInfoExt();
            adInfoExt.adunit_id = advertConfig.getPlacementId();
            adInfoExt.adunit_format = AdUnitFormat.NATIVE.getValue();
            advertCallback.onAdvertRequestAlt(this, adInfoExt);
        }
    }

    private void onAdvertLoaded(boolean adLoadedReal) {
        if (adLoadedReal) {
            onAdvertRequestAlt();
        }
        if (advertCallback != null) {
            advertCallback.onAdvertLoaded(this);
        }
        if (advertConfig.isShowAfterLoaded()) {
            showAdvert();
        }
    }

    private void onAdvertLoadFail(String adError) {
        if (isAdvertLoadFailed) return;
        isAdvertLoadFailed = true;

        if (advertCallback != null) {
            advertCallback.onAdvertLoadFail(this, adError);
        }
    }

    private void onAdvertShowFail() {
        if (advertCallback != null) {
            advertCallback.onAdvertShowFail(this);
        }
    }

    @Override
    public void onNativeAdLoaded() {
        onAdvertLoaded(true);
    }

    @Override
    public void onNativeAdLoadFail(AdError adError) {
        onAdvertLoadFail(adError != null ? adError.toString() : null);
    }

    @Override
    public void onAdImpressed(ATNativeAdView atNativeAdView, ATAdInfo atAdInfo) {
        if (advertCallback != null) {
            advertCallback.onAdvertShow(this, atAdInfo);
        }
        if (advertConfig.isPreloadAdvert()) {
            final NativeAdvertConfig nativeAdvertConfig
                    = AdvertGsonUtils.getInstance().deepClone(advertConfig, NativeAdvertConfig.class);
            if (nativeAdvertConfig != null) {
                nativeAdvertConfig.setShowAfterLoaded(false);

                final NativeAdvert nativeAdvert = new NativeAdvert(lifecycleOwner, nativeAdvertConfig);
                nativeAdvert.loadAdvert(true);
            }
        }
    }

    @Override
    public void onAdClicked(ATNativeAdView atNativeAdView, ATAdInfo atAdInfo) {
        if (advertCallback != null) {
            advertCallback.onAdvertClicked(this, atAdInfo);
        }
    }

    @Override
    public void onAdVideoStart(ATNativeAdView atNativeAdView) {
    }

    @Override
    public void onAdVideoEnd(ATNativeAdView atNativeAdView) {
    }

    @Override
    public void onAdVideoProgress(ATNativeAdView atNativeAdView, int i) {
    }
}
